#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <string.h>

#ifndef ITERATION_H
#define ITERATION_H

void iterate_start(DIR** iterator, char* path) {
    if ((*iterator = opendir(path)) == NULL) {
        perror("could not open dir");
        exit(-1);
    }
}

void iterate_start_users(DIR** iterator) {
    char path[64];
    sscanf(path, "/");

    iterate_start(iterator, path);
}

void iterate_start_units(DIR** iterator, char* user) {
    char path[64];
    sscanf(path, "/%s", user);

    iterate_start(iterator, path);
}

int iterate_next(DIR* iterator, char* value) {
    struct dirent* root_entry;
    while ((root_entry = readdir(iterator)) != NULL) {
        if (root_entry->d_type != DT_DIR) {
            continue;
        }

        // TODO: improve user recognition
        if (strlen(root_entry->d_name) < 3) {
            continue;
        }

        strcpy(value, root_entry->d_name);
        return 0;
    }
    closedir(iterator);
    return 1;
}

void iterate_users(UserIterator iterator, void* context) {
    DIR* root_dir;
    if ((root_dir = opendir("/")) == NULL) {
        perror("could not open root dir");
        exit(-1);
    }

    closedir(root_dir);
}

void iterate_units(char* user, UnitIterator iterator, void* context) {
    char user_dir_name[64];
    sprintf(user_dir_name, "/%s", user);

    DIR* user_dir;
    if ((user_dir = opendir(user_dir_name)) == NULL) {
        perror("could not open user dir");
        exit(-1);
    }

    struct dirent* user_entry;
    while ((user_entry = readdir(user_dir)) != NULL) {
        if (user_entry->d_type != DT_DIR) {
            continue;
        }

        if (strlen(user_entry->d_name) < 3) {
            continue;
        }

	(*iterator)(user, user_entry->d_name, context);
    }

    closedir(user_dir);
}

typedef struct {
    void* context;
    UnitIterator iterator;
} PassUserContext;
void pass_user(char* user, void* context) {
    PassUserContext* c = (PassUserContext*)context;
    iterate_units(user, c->iterator, c->context);
}
void iterate_all_units(UnitIterator iterator, void* context) {
    PassUserContext c;
    c.context = context;
    c.iterator = iterator;

    iterate_users(&pass_user, (void*)&c);
}

DIR* create_user_iterator() {
    DIR* root_dir;
    if ((root_dir = opendir("/")) == NULL) {
        perror("could not open root dir");
        exit(-1);
    }

    return root_dir;
}

DIR* create_unit_iterator(char* user) {
    char user_dir_name[64];
    sprintf(user_dir_name, "/%s", user);

    DIR* user_dir;
    if ((user_dir = opendir(user_dir_name)) == NULL) {
        perror("could not open user dir");
        exit(-1);
    }

    return user_dir;
}

char* next_user(DIR* user_it) {
    struct dirent* user_entry;
    while ((user_entry = readdir(user_it)) != NULL) {
        if (user_entry == NULL) {
            closedir(user_it);
            return NULL;
        }

        if (user_entry->d_type != DT_DIR) {
            continue;
        }

        if (strlen(user_entry->d_name) < 3) {
            continue;
        }

        return user_entry->d_name;
    }

    return NULL;
}

#endif
